using System;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Sockets;
using HslCommunication.BasicFramework;
using Newtonsoft.Json;

namespace HslCommunication
{
	/// <summary>
	/// 扩展的辅助类方法
	/// </summary>
	public static class HslExtension
	{
		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ByteToHexString(System.Byte[])" />
		public static string ToHexString(this byte[] InBytes)
		{
			return SoftBasic.ByteToHexString(InBytes);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ByteToHexString(System.Byte[],System.Char)" />
		public static string ToHexString(this byte[] InBytes, char segment)
		{
			return SoftBasic.ByteToHexString(InBytes, segment);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ByteToHexString(System.Byte[],System.Char,System.Int32)" />
		public static string ToHexString(this byte[] InBytes, char segment, int newLineCount)
		{
			return SoftBasic.ByteToHexString(InBytes, segment, newLineCount);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.HexStringToBytes(System.String)" />
		public static byte[] ToHexBytes(this string value)
		{
			return SoftBasic.HexStringToBytes(value);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.BoolOnByteIndex(System.Byte,System.Int32)" />
		public static bool GetBoolOnIndex(this byte value, int offset)
		{
			return SoftBasic.BoolOnByteIndex(value, offset);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.BoolArrayToByte(System.Boolean[])" />
		public static byte[] ToByteArray(this bool[] array)
		{
			return SoftBasic.BoolArrayToByte(array);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ByteToBoolArray(System.Byte[],System.Int32)" />
		public static bool[] ToBoolArray(this byte[] InBytes, int length)
		{
			return SoftBasic.ByteToBoolArray(InBytes, length);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ByteToBoolArray(System.Byte[])" />
		public static bool[] ToBoolArray(this byte[] InBytes)
		{
			return SoftBasic.ByteToBoolArray(InBytes);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArrayRemoveDouble``1(``0[],System.Int32,System.Int32)" />
		public static T[] RemoveDouble<T>(this T[] value, int leftLength, int rightLength)
		{
			return SoftBasic.ArrayRemoveDouble(value, leftLength, rightLength);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArrayRemoveBegin``1(``0[],System.Int32)" />
		public static T[] RemoveBegin<T>(this T[] value, int length)
		{
			return SoftBasic.ArrayRemoveBegin(value, length);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArrayRemoveLast``1(``0[],System.Int32)" />
		public static T[] RemoveLast<T>(this T[] value, int length)
		{
			return SoftBasic.ArrayRemoveLast(value, length);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArraySelectMiddle``1(``0[],System.Int32,System.Int32)" />
		public static T[] SelectMiddle<T>(this T[] value, int index, int length)
		{
			return SoftBasic.ArraySelectMiddle(value, index, length);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArraySelectBegin``1(``0[],System.Int32)" />
		public static T[] SelectBegin<T>(this T[] value, int length)
		{
			return SoftBasic.ArraySelectBegin(value, length);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArraySelectLast``1(``0[],System.Int32)" />
		public static T[] SelectLast<T>(this T[] value, int length)
		{
			return SoftBasic.ArraySelectLast(value, length);
		}

		/// <summary>
		/// 将指定的数据添加到数组的每个元素上去，使用表达式树的形式实现，将会修改原数组。不适用byte类型
		/// </summary>
		/// <typeparam name="T">数组的类型</typeparam>
		/// <param name="array">原始数据</param>
		/// <param name="value">数据值</param>
		/// <returns>返回的结果信息</returns>
		public static T[] IncreaseBy<T>(this T[] array, T value)
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "first");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(T), "second");
			Expression body = Expression.Add(parameterExpression, parameterExpression2);
			Expression<Func<T, T, T>> expression = Expression.Lambda<Func<T, T, T>>(body, new ParameterExpression[2]
			{
				parameterExpression,
				parameterExpression2
			});
			Func<T, T, T> func = expression.Compile();
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = func(array[i], value);
			}
			return array;
		}

		/// <summary>
		/// 拷贝当前的实例数组，是基于引用层的浅拷贝，如果类型为值类型，那就是深度拷贝，如果类型为引用类型，就是浅拷贝
		/// </summary>
		/// <typeparam name="T">类型对象</typeparam>
		/// <param name="value">数组对象</param>
		/// <returns>拷贝的结果内容</returns>
		public static T[] CopyArray<T>(this T[] value)
		{
			if (value == null)
			{
				return null;
			}
			T[] array = new T[value.Length];
			Array.Copy(value, array, value.Length);
			return array;
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArrayFormat``1(``0[])" />
		public static string ToArrayString<T>(this T[] value)
		{
			return SoftBasic.ArrayFormat(value);
		}

		/// <inheritdoc cref="M:HslCommunication.BasicFramework.SoftBasic.ArrayFormat``1(``0,System.String)" />
		public static string ToArrayString<T>(this T[] value, string format)
		{
			return SoftBasic.ArrayFormat(value, format);
		}

		/// <summary>
		/// 将字符串数组转换为实际的数据数组。例如字符串格式[1,2,3,4,5]，可以转成实际的数组对象<br />
		/// Converts a string array into an actual data array. For example, the string format [1,2,3,4,5] can be converted into an actual array object
		/// </summary>
		/// <typeparam name="T">类型对象</typeparam>
		/// <param name="value">字符串数据</param>
		/// <param name="selector">转换方法</param>
		/// <returns>实际的数组</returns>
		public static T[] ToStringArray<T>(this string value, Func<string, T> selector)
		{
			if (value.IndexOf('[') >= 0)
			{
				value = value.Replace("[", "");
			}
			if (value.IndexOf(']') >= 0)
			{
				value = value.Replace("]", "");
			}
			string[] source = value.Split(new char[1]
			{
				','
			}, StringSplitOptions.RemoveEmptyEntries);
			return source.Select(selector).ToArray();
		}

		/// <summary>
		/// 将字符串数组转换为实际的数据数组。支持byte,sbyte,bool,short,ushort,int,uint,long,ulong,float,double，使用默认的十进制，例如字符串格式[1,2,3,4,5]，可以转成实际的数组对象<br />
		/// Converts a string array into an actual data array. Support byte, sbyte, bool, short, ushort, int, uint, long, ulong, float, double, use the default decimal, 
		/// such as the string format [1,2,3,4,5], which can be converted into an actual array Object
		/// </summary>
		/// <typeparam name="T">类型对象</typeparam>
		/// <param name="value">字符串数据</param>
		/// <returns>实际的数组</returns>
		public static T[] ToStringArray<T>(this string value)
		{
			Type typeFromHandle = typeof(T);
			if (typeFromHandle == typeof(byte))
			{
				return (T[])(object)value.ToStringArray(byte.Parse);
			}
			if (typeFromHandle == typeof(sbyte))
			{
				return (T[])(object)value.ToStringArray(sbyte.Parse);
			}
			if (typeFromHandle == typeof(bool))
			{
				return (T[])(object)value.ToStringArray(bool.Parse);
			}
			if (typeFromHandle == typeof(short))
			{
				return (T[])(object)value.ToStringArray(short.Parse);
			}
			if (typeFromHandle == typeof(ushort))
			{
				return (T[])(object)value.ToStringArray(ushort.Parse);
			}
			if (typeFromHandle == typeof(int))
			{
				return (T[])(object)value.ToStringArray(int.Parse);
			}
			if (typeFromHandle == typeof(uint))
			{
				return (T[])(object)value.ToStringArray(uint.Parse);
			}
			if (typeFromHandle == typeof(long))
			{
				return (T[])(object)value.ToStringArray(long.Parse);
			}
			if (typeFromHandle == typeof(ulong))
			{
				return (T[])(object)value.ToStringArray(ulong.Parse);
			}
			if (typeFromHandle == typeof(float))
			{
				return (T[])(object)value.ToStringArray(float.Parse);
			}
			if (typeFromHandle == typeof(double))
			{
				return (T[])(object)value.ToStringArray(double.Parse);
			}
			throw new Exception("use ToArray<T>(Func<string,T>) method instead");
		}

		/// <summary>
		/// 启动接收数据，需要传入回调方法，传递对象<br />
		/// To start receiving data, you need to pass in a callback method and pass an object
		/// </summary>
		/// <param name="socket">socket对象</param>
		/// <param name="callback">回调方法</param>
		/// <param name="obj">数据对象</param>
		/// <returns>是否启动成功</returns>
		public static OperateResult BeginReceiveResult(this Socket socket, AsyncCallback callback, object obj)
		{
			try
			{
				socket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, callback, obj);
				return OperateResult.CreateSuccessResult();
			}
			catch (Exception ex)
			{
				socket?.Close();
				return new OperateResult(ex.Message);
			}
		}

		/// <summary>
		/// 启动接收数据，需要传入回调方法，传递对象默认为socket本身<br />
		/// To start receiving data, you need to pass in a callback method. The default object is the socket itself.
		/// </summary>
		/// <param name="socket">socket对象</param>
		/// <param name="callback">回调方法</param>
		/// <returns>是否启动成功</returns>
		public static OperateResult BeginReceiveResult(this Socket socket, AsyncCallback callback)
		{
			return socket.BeginReceiveResult(callback, socket);
		}

		/// <summary>
		/// 结束挂起的异步读取，返回读取的字节数，如果成功的情况。<br />
		/// Ends the pending asynchronous read and returns the number of bytes read, if successful.
		/// </summary>
		/// <param name="socket">socket对象</param>
		/// <param name="ar">回调方法</param>
		/// <returns>是否启动成功</returns>
		public static OperateResult<int> EndReceiveResult(this Socket socket, IAsyncResult ar)
		{
			try
			{
				return OperateResult.CreateSuccessResult(socket.EndReceive(ar));
			}
			catch (Exception ex)
			{
				socket?.Close();
				return new OperateResult<int>(ex.Message);
			}
		}

		/// <summary>
		/// 获取当前对象的JSON格式表示的字符串。<br />
		/// Gets the string represented by the JSON format of the current object.
		/// </summary>
		/// <returns>字符串对象</returns>
		public static string ToJsonString(this object obj, Formatting formatting = Formatting.Indented)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return JsonConvert.SerializeObject(obj, formatting);
		}
	}
}
